import { pauseTrack, resumeTrack, track, trigger } from "./effect.js";
import { TrackOpTypes, TriggerOpTypes } from "./operations.js";
import { reactive } from "./reactive.js";
import { hasChanged, isObject } from "./utils.js";

const obj = {
    indexOf: () => { },
    includes: () => { },
    lastIndexOf: () => { }
};

const arrayInstrumentations = {};
const RAW = Symbol('raw');

['indexOf', 'includes', 'lastIndexOf'].forEach(key => {
    arrayInstrumentations[key] = function (...args) {
        // 1. 正常找
        const res = Array.prototype[key].apply(this, args);
        // 2. 找不到，从原始对象找
        if (res < 0 || res === false) {
            return Array.prototype[key].apply(this[RAW], args);
        }
        return res;
    }
});


['push', 'pop', 'shift', 'unshift', 'splice'].forEach(key => {
    arrayInstrumentations[key] = function (...args) {
        pauseTrack(); // 暂停搜集
        const res = Array.prototype[key].apply(this, args);
        resumeTrack();
        return res; // 开始搜集
    }
});

function get(target, key, receiver) {
    if (key === RAW) {
        return target;
    }
    // 信息收集
    track(target, TrackOpTypes.GET, key);

    if (arrayInstrumentations.hasOwnProperty(key) && Array.isArray(target)) {
        return arrayInstrumentations[key];
    }

    const result = Reflect.get(target, key, receiver); // 返回对象相应的属性值
    if (isObject(result)) {
        return reactive(result);
    }
    return result;
}
function set(target, key, value, receiver) {
    const type = target.hasOwnProperty(key)
        ? TriggerOpTypes.SET
        : TriggerOpTypes.ADD;
    const oldValue = target[key];
    const targetIsArray = Array.isArray(target);
    const oldLength = targetIsArray ? target.length : undefined;

    const result = Reflect.set(target, key, value, receiver); // 设置对象的属性值
    if (!result) {
        return result;
    }

    const newLength = targetIsArray ? target.length : undefined;

    if (hasChanged(oldValue, value) || type === TriggerOpTypes.ADD) {
        // 派发更新
        trigger(target, TriggerOpTypes.SET, key);

        if (targetIsArray && oldLength !== newLength) {
            if (key !== 'length') {
                trigger(target, TriggerOpTypes.SET, 'length');
            } else {
                for (var i = newLength; i < oldLength; i++) {
                    trigger(target, TriggerOpTypes.DELETE, i.toString());
                }
            }
        }
    }
    return result;
}
function has(target, key) {
    track(target, TrackOpTypes.HAS, key);
    return Reflect.has(target, key);
}
function ownKeys(target) {
    // 依赖收集
    track(target, TrackOpTypes.ITERATE);
    return Reflect.ownKeys(target); // 返回对象的所有属性名
}

function deleteProperty(target, key) {
    const hadKey = target.hasOwnProperty(key);
    const result = Reflect.deleteProperty(target, key);
    // 依赖收集
    if (hadKey && result) {
        trigger(target, TriggerOpTypes.DELETE, key);
    }
    return result; // 删除对象的相应属性
}

export const handlers = {
    get,
    set,
    has,
    ownKeys,
    deleteProperty
}